home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
exampleCode
/
opengl
/
extensions
/
samples
/
volspin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-11
|
15KB
|
583 lines
/*
* Copyright (c) 1995 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that (i) the above copyright notices and this permission
* notice appear in all copies of the software and related documentation,
* and (ii) the name of Silicon Graphics may not be used in any
* advertising or publicity relating to the software without the specific,
* prior written permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
* INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
/*
* volspin.c - simple demo of 3D textures.
* A 3D texture of a cube with a cubical cavity is constructed.
* The "npolys" polygons that are parallel to the screen are displayed with
* the texture mapped onto them.
* To acheive rotation of the displayed volume (the cube), transformations are
* applied to the texture coordinate by modifying the texture matrix.
*
* See usage function for options.
*
* $Revision: 1.1 $
*
* Note: In 5.3 (and patch154) and earlier, RealityEngine has bug in the texture
* matrix push/pop on RealityEngine, where the matrix is not properly restored
* after pops. This code has a workaround for this bug which is envoked when
* #define PUSH_TEX_MAT_BUG is 1.
*/
#include <stdlib.h>
#include <stdio.h>
#include <bstring.h>
#include <string.h>
#include <math.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include <X11/keysym.h>
#include <Xm/MwmUtil.h>
#include "util.h"
#define W 600
#define H 600
#if !defined(GL_EXT_texture3D) || !defined(GL_EXT_texture)
Sorry either EXT_texture3D or EXT_texture is not supported by this library.
#endif
#define PUSH_TEX_MAT_BUG 1
long width = W, height = H;
Display *dpy;
Colormap cmap;
Window window;
XVisualInfo *vi;
GLXContext cx;
int tracking=False;
int usealpha=False;
int nslices=64;
int npolys=64;
int spindx = 0, spindy = 0;
int startx, starty;
int curx = 0, cury = 0;
void redraw(void);
void drawvolume(void);
void initTexMatrix(int fromInit);
Window createWindow(int argc, char **argv, Bool fullScreen);
typedef struct {
GLenum param; /* name in opengl */
char *string; /* what the user types */
} pair;
pair internaltab[] = {
{ GL_RGBA8_EXT, "rgba8" },
{ GL_RGB4_EXT, "rgb4" },
{ GL_RGB5_EXT, "rgb5" },
{ GL_RGB8_EXT, "rgb8" },
{ GL_RGB12_EXT, "rgb12" },
{ GL_RGBA4_EXT, "rgba4" },
{ GL_RGBA12_EXT, "rgba12" },
{ 0, NULL },
};
GLenum intfmt = GL_RGBA8_EXT;
char *istr = "rgba8";
#if PUSH_TEX_MAT_BUG
float textureMatrix[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
};
#define PUSH_TEX_MAT() glGetFloatv(GL_TEXTURE_MATRIX, textureMatrix)
#define POP_TEX_MAT() glLoadMatrixf(textureMatrix)
#else
#define PUSH_TEX_MAT() glPushMatrix()
#define POP_TEX_MAT() glPopMatrix()
#endif /* def PUSH_TEX_MAT_BUG */
pair *
lookuppair(pair tab[], char *name)
{
int i;
for (i=0; tab[i].param; i++) {
if (!strcmp(name, tab[i].string))
return &tab[i];
}
return NULL;
}
void eventloop(void)
{
XEvent event;
XButtonEvent *bev;
int x, y, size;
unsigned int w, h, bw, depth;
Window root;
for (;;) {
if (XPending(dpy)) {
XNextEvent(dpy, &event);
bev = (XButtonEvent *) &event;
switch (event.type) {
case KeyPress:
{
char buf[100];
int rv;
KeySym ks;
rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
switch (ks) {
case XK_Escape:
exit(EXIT_SUCCESS);
break;
case XK_Home:
initTexMatrix(False);
spindx = spindy = 0;
redraw();
break;
case XK_h:
case XK_question:
printf("Keys:\tHome - reset xform\n\tEsc - quit\n");
printf("To move the object press a mouse button\
and move the mouse\n");
break;
}
if (!XPending(dpy)) redraw();
}
break;
case Expose:
XGetGeometry(dpy, window, &root, &x, &y, &w, &h, &bw, &depth);
width = w;
height = h;
size = (width < height ? width : height);
glViewport((width-size)/2, (height-size)/2, size, size);
redraw();
break;
case ConfigureNotify:
width = event.xconfigure.width;
height = event.xconfigure.height;
size = (width < height ? width : height);
glViewport((width-size)/2, (height-size)/2, size, size);
redraw();
break;
case ButtonPress:
curx = startx = bev->x;
cury = starty = bev->y;
spindx = 0;
spindy = 0;
tracking = True;
break;
case ButtonRelease:
/*
* If user released the button while moving the mouse, keep
* spinning.
*/
if (bev->x != curx || bev->y != cury) {
spindx = bev->x - curx;
spindy = bev->y - cury;
}
tracking = False;
break;
case MotionNotify:
if (XPending(dpy)) break;
curx = bev->x;
cury = bev->y;
if (curx != startx || cury != starty) {
redraw();
startx = curx;
starty = cury;
}
break;
}
} else {
if (!tracking && (spindx!=0 || spindy!=0)) {
redraw();
}
}
}
}
#define IMAGEXSIZE 64
#define IMAGEYSIZE 64
#define IMAGEZSIZE 256
void
makeimage(int xsize, int ysize, char red, char green, char blue)
{
int i, j, k;
float s, t, r, ds, dt, dr;
unsigned char *p, *buf;
buf = (unsigned char *) malloc(xsize * ysize * nslices * 4);
ds = (xsize > 1 ? 1.0/(xsize-1) : 0);
dt = (ysize > 1 ? 1.0/(ysize-1) : 0);
dr = (nslices > 1 ? 1.0/(nslices-1) : 0);
for (i = 0; i < nslices; i++) {
r = i*dr;
for (j = 0; j < ysize; j++) {
t = j*dt;
for (k = 0; k < xsize; k++) {
s = k*ds;
if (usealpha) {
p = &buf[(i*xsize*ysize + j*xsize + k)*4];
} else {
p = &buf[(i*xsize*ysize + j*xsize + k)*3];
}
if (!(s > .23 && s < .76 &&
t > .23 && t < .76 &&
r > .23 && r < .76) &&
!((s < .05 || s > .95) ||
(t < .05 || t > .95) ||
(r < .05 || r > .95))) {
p[0] = red;
p[1] = green;
p[2] = blue;
} else {
p[0] = p[1] = p[2] = 0x00;
}
if (usealpha) {
p[3] = 256/nslices;
}
}
}
}
printf( "downloading texture..."); fflush(stdout);
if (usealpha) {
glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, intfmt, xsize, ysize, nslices,
0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
} else {
glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, intfmt, xsize, ysize, nslices,
0, GL_RGB, GL_UNSIGNED_BYTE, buf);
}
printf( ".. done\n");
}
void init(int argc, char **argv, int fullScreen)
{
int i;
window = createWindow(argc, argv, fullScreen );
cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
if (!glXMakeCurrent(dpy, window, cx)) {
fprintf(stderr, "Can't make window current to context\n");
exit(EXIT_FAILURE);
}
if (!getExtension("GL_EXT_texture3D") || !getExtension("GL_EXT_texture")) {
fprintf(stderr, "Sorry, renderer does not support either EXT_texture3D or\
EXT_texture extensions.\n");
exit(EXIT_FAILURE);
}
makeimage(IMAGEXSIZE,IMAGEYSIZE,0xff,0xff,0xff);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90.0, 1.0, 2.0, 20.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
initTexMatrix(True);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glClearColor(0.05,0.05,0.3,1.0);
glEnable(GL_TEXTURE_3D_EXT);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R_EXT, GL_CLAMP);
if (usealpha) {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
} else {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}
}
void drawvolume(void)
{
int i;
float du, u;
if (npolys > 1) {
du = 1.0 / (npolys-1);
} else {
du = 0.0;
}
glLoadIdentity();
glTranslatef(0.0,0.0,-10.0);
glNormal3f(0,0,-1);
glScalef(12, 12, 12);
glTranslatef(-.5,-.5,-.5);
if (usealpha) {
glColor4f(1, 1, 1, 1);
} else {
glColor4f(1,0.5,0.5,du * 1.3);
}
for (i=0; i < npolys; i++) {
u = i*du;
glBegin(GL_POLYGON);
glTexCoord3f(0, 0, 2*u); glVertex3f( 0, 0, u);
glTexCoord3f(2, 0, 2*u); glVertex3f( 1, 0, u);
glTexCoord3f(2, 2, 2*u); glVertex3f( 1, 1, u);
glTexCoord3f(0, 2, 2*u); glVertex3f( 0, 1, u);
glEnd();
}
}
void initTexMatrix(int fromInit)
{
#if PUSH_TEX_MAT_BUG
int i;
bzero(textureMatrix, sizeof(textureMatrix));
for (i = 0; i < 4; i++)
textureMatrix[4*i + i] = 1;
#endif
glMatrixMode(GL_TEXTURE);
if (!fromInit)
POP_TEX_MAT();
glLoadIdentity();
glScalef(.87,.87,.87);
glTranslatef(.5,.5,.5);
PUSH_TEX_MAT();
glMatrixMode(GL_MODELVIEW);
}
void redraw(void)
{
float dx, dy;
float len;
static GLuint vcount;
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_TEXTURE);
POP_TEX_MAT();
if (tracking) {
dx = curx - startx;
dy = cury - starty;
} else {
dx = spindx;
dy = spindy;
}
if (dx || dy) {
len = sqrt(dx * dx + dy * dy);
dx /= len;
dy /= len;
glRotatef(-0.5 * len, dy, dx, 0);
}
PUSH_TEX_MAT();
glTranslatef(-1,-1,-1);
glMatrixMode(GL_MODELVIEW);
drawvolume();
glXSwapBuffers(dpy, window);
}
static void usage(char *name, int exitStatus)
{
int i, len;
fprintf(stderr, "usage: %s [-f (full screen)] [-s #slices] [-p #polys]\
[-a(utospin)]\n", name);
fprintf(stderr,
"\t[-A (use alpha channel)] [-i `internal texture format'] [-h(elp)]\n");
fprintf(stderr, "\tInternal formats: ");
len = strlen("Internal formats: ");
for (i = 0; internaltab[i].param; i++) {
len += strlen(internaltab[i].string) + 2;
fprintf(stderr, "%s%s", internaltab[i].string,
internaltab[i + 1].param == 0 ? "\n" : (len > 65 ? "\n\t\t" : ", "));
if (len > 65)
len = 0;
}
fprintf(stderr,
"\tInteractively, `h/?' keys provide description of interface\n");
exit(exitStatus);
}
int main(int argc, char **argv)
{
int i;
int fullScreen=0;
pair *pp;
for (i=1; i<argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 's':
i++;
if (i > argc) {
fprintf(stderr, "Missing argument for `-s' option\n");
usage(argv[0], EXIT_FAILURE);
}
nslices = atoi(argv[i]);
break;
case 'p':
i++;
if (i >= argc) {
fprintf(stderr, "Missing argument for `-p' option\n");
usage(argv[0], EXIT_FAILURE);
}
npolys = atoi(argv[i]);
break;
case 'f':
fullScreen = True;
break;
case 'a':
spindx = spindy = 20;
break;
case 'A':
usealpha = True;
break;
case 'i':
i++;
if (i >= argc) {
fprintf(stderr, "Missing argument for `-i' option\n");
usage(argv[0], EXIT_FAILURE);
}
pp = lookuppair(internaltab, argv[i]);
if (pp == NULL) {
fprintf(stderr, "Unreconized internal format argument (`%s')\
for `-i' option\n", argv[i]);
exit(EXIT_FAILURE);
}
intfmt = pp->param;
istr = pp->string;
break;
case 'h':
usage(argv[0], EXIT_SUCCESS);
/* usage never returnes */
default:
fprintf(stderr, "Bad option `%s'\n", argv[i]);
usage(argv[0], EXIT_FAILURE);
}
} else {
fprintf(stderr, "Bad option `%s'\n", argv[i]);
usage(argv[0], EXIT_FAILURE);
}
}
init(argc, argv, fullScreen);
printf("using internal format: %-6s\n", istr);
eventloop();
glXMakeCurrent(dpy, None, NULL);
glXDestroyContext(dpy, cx);
XCloseDisplay(dpy);
}
/****************************************************************************/
/*
* Create an X window.
*/
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
return GL_TRUE;
}
return GL_FALSE;
}
Window createWindow( int argc, char **argv, Bool fullScreen )
{
Window window;
XSetWindowAttributes swa;
XSizeHints sh;
XEvent event;
int attributes[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
None,
};
dpy = XOpenDisplay(0);
if (!dpy) {
fprintf(stderr, "Can't connect to display \"%s\"\n",
getenv("DISPLAY"));
exit(EXIT_FAILURE);
}
vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
if (!vi) {
fprintf(stderr, "Cannot find required visual on \"%s\"\n",
getenv("DISPLAY"));
exit(EXIT_FAILURE);
}
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
AllocNone);
swa.background_pixel = 0;
swa.border_pixel = 0;
swa.colormap = cmap;
swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
KeyReleaseMask | ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
if (fullScreen) {
width = DisplayWidth( dpy, 0 );
height = DisplayHeight( dpy, 0 );
sh.x = 0;
sh.y = 0;
} else {
sh.x = 50;
sh.y = 50;
}
sh.flags = USPosition | PPosition;
window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), sh.x, sh.y,
width, height,
0, vi->depth, InputOutput, vi->visual,
CWBorderPixel|CWColormap|CWEventMask|CWBackPixel,
&swa);
XSetStandardProperties(dpy, window, argv[0], argv[0],
None, argv, argc, &sh);
XSetWMColormapWindows(dpy, window, &window, 1);
if (fullScreen) {
/* turn off window decorations */
Atom hints_atom;
MotifWmHints hints;
hints_atom = XInternAtom( dpy, "_MOTIF_WM_HINTS", 0 );
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0;
XChangeProperty( dpy, window, hints_atom, hints_atom, 32,
PropModeReplace, (unsigned char*)&hints, 5 );
}
XMapWindow(dpy, window);
XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
return window;
}